﻿#region License
/*
 * Microsoft Public License (Ms-PL)
 * 
 * This license governs use of the accompanying software. If you use the software, you accept this license. 
 * If you do not accept the license, do not use the software.
 *
 * 1. Definitions
 *
 * The terms "reproduce," "reproduction," "derivative works," and "distribution" have the same meaning here as under U.S. copyright law.
 *
 * A "contribution" is the original software, or any additions or changes to the software.
 *
 * A "contributor" is any person that distributes its contribution under this license.
 *
 * "Licensed patents" are a contributor's patent claims that read directly on its contribution.
 *
 * 2. Grant of Rights
 *
 * (A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, 
 * each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, 
 * prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create.
 *
 * (B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, 
 * each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, 
 * use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the 
 * contribution in the software.
 *
 * 3. Conditions and Limitations
 *
 * (A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks.
 *
 * (B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, 
 * your patent license from such contributor to the software ends automatically.
 *
 * (C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, 
 * and attribution notices that are present in the software.
 *
 * (D) If you distribute any portion of the software in source code form, you may do so only under this license by including 
 * a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, 
 * you may only do so under a license that complies with this license.
 *
 * (E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. 
 * You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, 
 * the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement. 
 */
#endregion

#region Usings
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Drawing;
using System.Windows.Forms;
using System.ComponentModel;
#endregion

#region Namespace
namespace XMLSpriteSheets
{
    #region Class
    public class XMLReader
    {
        #region Fields and Properties
        /// <summary>
        /// The XML File we read
        /// </summary>
        XmlDocument xmlLayout = new XmlDocument();

        /// <summary>
        /// Dictionary to hold all the XML data
        /// </summary>
        Dictionary<string, Image> allFrames = new Dictionary<string, Image>();

        /// <summary>
        /// Our main form so we can print to it
        /// </summary>
        mainFrm MainForm { get; set; }

        RichTextBox Output { get; set; }

        ProgressBar progressBar { get; set; }

        List<Image> spriteList = new List<Image>();

        BackgroundWorker worker { get; set; }

        #endregion

        #region Constructor
        public XMLReader(mainFrm form)
        {
            MainForm = form;
            Output = MainForm.rtf_Console;
            progressBar = form.progressBar;
            worker = form.bw;
        }
        #endregion

        #region Class Functions
        /// <summary>
        /// File Reading Function
        /// </summary>
        /// <param name="file"></param>
        /// <returns></returns>
        public Dictionary<string, Image> ReadSP(string file, Image img)
        {
                decimal filesLoaded = 0;

                decimal percent = 0;


                //Open Load and read the xml
                xmlLayout.Load(file);
                // Clear it all
                allFrames.Clear();
                spriteList.Clear();

                // Need to test here, if the layout matches Texture packer or spritesheetpacker
                XmlNodeList frameNodes = xmlLayout.SelectNodes("/XnaContent/Asset");

                progressBar.BeginInvoke(new MethodInvoker(delegate
                    {
                        progressBar.Value = 0;
                    }));


                foreach (XmlNode node in frameNodes)
                {
                    decimal filesLeftToLoad = node.ChildNodes.Count;

                    foreach (XmlNode n2 in node)
                    {

                            //Ok here is where all our entries are
                            //<Item><Key>Ranger_NW_8AttackMid_00</Key><Value>0 0 512 512</Value></Item>
                            // I want key.value and value.value
                            string frameName = n2["Key"].InnerText;
                            // Have to split the rectangle value, its a string atm
                            // with X Y Width Height
                            string formatted = n2["Value"].InnerText;

                            Rectangle rect = new Rectangle();

                            string[] brokenDown = formatted.Split(' ');

                            for (int i = 0; i < brokenDown.Length; i++)
                            {
                                rect = new Rectangle(int.Parse(brokenDown[0]), int.Parse(brokenDown[1]),
                                  int.Parse(brokenDown[2]), int.Parse(brokenDown[3]));
                            }
                            Size size = new Size(rect.Width, rect.Height);

                            Image newImage = cropImage(img, rect, size);
                            percent = Math.Round((filesLoaded / filesLeftToLoad) * 100);
                            worker.ReportProgress((int)percent);
                            allFrames.Add(frameName, newImage);

                            filesLoaded++;
                        }
                    }
                
            return allFrames;
        }

        public Dictionary<string, Image> ReadTP(string file, Image img)
        {

                xmlLayout.Load(file);

                // Clear it all
                allFrames.Clear();
                spriteList.Clear();

                XmlNodeList frameNodes = xmlLayout.SelectNodes("/TextureAtlas");

                foreach (XmlNode node in frameNodes)
                {

                    foreach (XmlNode n2 in node)
                    {

                            /* Eureka !!!
                             * 0 = Frame name
                             * 1 = X
                             * 2 = Y
                             * 3 = w
                             * 4 = h
                             */
                            // Ok some of these are filpped, flip em back
                            if (n2.Attributes.Count == 10) // Only flipped images have this attribute, and are filpped clockwise
                            {

                                // get the rectangle, and grab the image, flipp it counterclockwise
                                // add the image
                                Rectangle rect = new Rectangle(
                                int.Parse(n2.Attributes[1].InnerText),
                                int.Parse(n2.Attributes[2].InnerText),
                                int.Parse(n2.Attributes[3].InnerText),
                                int.Parse(n2.Attributes[4].InnerText));

                                Size size = new Size(rect.Width, rect.Height);

                                Image newImage;

                                newImage = cropImage(img, rect, size);

                                // Flipp it
                                if (newImage != null) { newImage.RotateFlip(RotateFlipType.Rotate270FlipNone); }
                                else { MainForm.bw.CancelAsync(); }
                                allFrames.Add(n2.Attributes[0].InnerText, newImage);
                            }
                            else
                            {
                                // Just rip the image
                                Rectangle rect = new Rectangle(
                                    int.Parse(n2.Attributes[1].InnerText),
                                    int.Parse(n2.Attributes[2].InnerText),
                                    int.Parse(n2.Attributes[3].InnerText),
                                    int.Parse(n2.Attributes[4].InnerText));

                                Size size = new Size(rect.Width, rect.Height);
                                Image newImage;
                                newImage = cropImage(img, rect, size);
                                allFrames.Add(n2.Attributes[0].InnerText, newImage);

                            }


                        }
                    }
                
            return allFrames;
        }
        #endregion


        /// <summary>
        /// 
        /// </summary>
        /// <param name="img"></param>
        /// <param name="cropArea"></param>
        /// <param name="size"></param>
        /// <returns></returns>
        private  Image cropImage(Image img, Rectangle cropArea, Size size)
        {
            Bitmap bmpImage = null;

            Bitmap bmpCrop = null;
            // If this errors out its because the XML file and the Image do NOT match
            try
            {
                bmpImage = new Bitmap(img);
                bmpCrop = bmpImage.Clone(cropArea,
                bmpImage.PixelFormat);
                

            }
            catch
            {
                if (Output.InvokeRequired)
                {
                    Output.BeginInvoke(new MethodInvoker(delegate { Output.AppendText("Unable to load Sheet, possibly mismatched xml and sprite sheet ?\n"); }));
                }
                else
                {
                    Output.AppendText("Unable to load Sheet, possibly mismatched xml and sprite sheet ?\n");
                }
                Stop();
            }
            return (Image)bmpCrop;
        }


        public  void Stop()
        {
            // Clear everything
            MainForm.bw.CancelAsync();
            MainForm.bw.Dispose();
        }
    }
    #endregion Class
}
#endregion Namespace